#include "mapdrawer.h"

MapDrawer::MapDrawer() : scale_(15), area_size_(1000 / scale_)
{
}

MapDrawer::MapDrawer(HWND const & hwnd) : hwnd_(hwnd), dc_(GetDC(hwnd)), scale_(1)
{
}

void MapDrawer::clear()
{
	objects_.clear();
	ReleaseDC(hwnd_, dc_);
}

bool MapDrawer::empty() const
{
	return objects_.empty();
}

void MapDrawer::setHWND(HWND const & hWnd)
{
	if(objects_.size() > 0)
	{
		ReleaseDC(hwnd_, dc_);
		hwnd_ = hWnd;
		dc_ = GetDC(hWnd);
	} 
	else
	{
		hwnd_ = hWnd;
	}
}

HWND MapDrawer::getHWND() const
{
	return hwnd_;
}

void MapDrawer::setData(DBMaster const & data)
{
	data_ = data;
	
	clear();

	scale_ = 15;
	cell_pos pos = data_.cells.cbegin()->second.cell_id;
	position_ = point_t(pos.first - area_size_ / 2, pos.second - area_size_ / 2);

	std::vector<int> const & idxs = data_.cells.cbegin()->second.objects;
	map_obj::const_iterator it = data_.map_objects.cbegin();
	for(size_t i = 0; i < idxs.size(); ++i)
	{
		map_obj::iterator it = data_.map_objects.find(idxs[i]);
		if (it != data_.map_objects.end())
			add(getobject(& it->second));
	}

	std::vector<MAP_OBJECT> objs;
	for(map_obj::const_iterator it = data.map_objects.begin(); it != data.map_objects.end(); ++it)
	{
		objs.push_back(it->second);
	}

	locator_ = point_locator_t(objs, 5);
	redraw();
}

DBMaster MapDrawer::getData() const
{
	return data_;
}
	
void MapDrawer::border() const
{
	RECT rect;
	GetClientRect(hwnd_, &rect);
	SelectObject(dc_, CreateSolidBrush(GetSysColor(5)));
	Rectangle(dc_, 0, 0, (rect.right - rect.left), (rect.bottom - rect.top));
}

void MapDrawer::add(object * obj)
{
	if(objects_.size() == 0)
		dc_ = GetDC(hwnd_);
    int i = obj->getid();
	objects_.insert(obpair(i, obj));
}

void MapDrawer::draw() const
{
	RECT rect;
	GetClientRect(hwnd_, &rect);
	int width = rect.right - rect.left;
	int height = rect.bottom - rect.top;
	
	HDC hdc_mem = CreateCompatibleDC(dc_);
	HBITMAP hbm_mem = CreateCompatibleBitmap(dc_, width, height);
	HANDLE h_old   = SelectObject(hdc_mem, hbm_mem);
	
	SelectObject(hdc_mem, CreateSolidBrush(GetSysColor(5)));
	Rectangle(hdc_mem, 0, 0, width, height);

	objectmap::const_iterator oitr = objects_.end();
	for(oitr = objects_.begin(); oitr != objects_.end(); ++oitr)
	{
		oitr->second->draw(&hdc_mem, scale_, position_);
	}
	BitBlt(dc_, 0, 0, width, height, hdc_mem, 0, 0, SRCCOPY);

	SelectObject(hdc_mem, h_old);
    DeleteObject(hbm_mem);
    DeleteDC    (hdc_mem);
}

void MapDrawer::redraw() const
{
	border();
	draw();
}

void MapDrawer::zoomIn()
{
	if (scale_ < 30)
	{
		scale_ *= 1.2;
		area_size_ = 1000 / scale_;
		redraw();
	}
}

void MapDrawer::zoomOut()
{
	if (scale_ > 4)
	{
		scale_ /= 1.2;
		area_size_ = 1000 / scale_;
		redraw();
	}
}

void MapDrawer::moveLeft()
{
	RECT rect;
	GetClientRect(hwnd_, &rect);
	position_.x += (rect.right - rect.left) / 3 / scale_;
	redraw();
}

void MapDrawer::moveRight()
{ 
	RECT rect;
	GetClientRect(hwnd_, &rect);
	position_.x -= (rect.right - rect.left) / 3 / scale_;
	redraw();
}

void MapDrawer::moveTop()
{
	RECT rect;
	GetClientRect(hwnd_, &rect);
	position_.y += (rect.bottom - rect.top) / 3 / scale_;
	redraw();
}

void MapDrawer::moveBottom()
{
	RECT rect;
	GetClientRect(hwnd_, &rect);
	position_.y -= (rect.bottom - rect.top) / 3 / scale_;
	redraw();
}

void MapDrawer::getTip(POINT point) const
{
	point_t p = PTCON(point, scale_, position_);
	int idx = locator_.inside(p);
	map_obj::const_iterator it = data_.map_objects.find(idx);
	std::string str;
	if (it != data_.map_objects.end())
		str = std::string(it->second.label);
	else str = "";
	SelectObject(dc_, CreateSolidBrush(GetSysColor(5)));
	Rectangle(dc_, 0, 0, 300, 25);
	TextOut(dc_, 5, 5, str.c_str(), str.size());
}
